<?php

declare(strict_types=1);
/**
 * api base
 */
namespace App\Controller;

use App\Constants\ErrorCode;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\Logger\LoggerFactory;
use Hyperf\Codec\Json;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;
use function Hyperf\Support\env;

class ApiController extends AbstractController
{
    private int|string $code = 1002;
    private array|object $data = [];
    #[Inject]
    protected LoggerInterface $logger;

    /**
     * @var mixed|string
     */
    protected mixed $ip;

    public function __construct(LoggerFactory $loggerFactory)
    {
        // 第一个参数对应日志的 name, 第二个参数对应 config/autoload/logger.php 内的 key
        $this->logger = $loggerFactory->get('log', 'default');
        $this->ip = $this->request->getHeaderLine('x-real-ip') ?: $this->request->getHeaderLine('x-forwarded-for') ?: $this->request->getServerParams()['remote_addr'];
    }

    /**
     * Notes:返回信息
     * 2024/5/28
     * @param int|string $errorLine 异常相关行号
     * @param string $errorFile 产生异常的文件名
     * @param string $message 异常信息
     * @return ResponseInterface
     * @throws \Exception
     */
    public function responseJson(int|string $errorLine = 0, string $errorFile = "", string $message = ""): ResponseInterface
    {
        $message = $message ?: ErrorCode::getMessage($this->code);
        $errorDetail = [
            'code' => $this->code,
            'message' => $message,
            'errorLine' => $errorLine,
            'errorFile' => $errorFile,
        ];

        if ($this->code !== ErrorCode::SUCCESS) {
            $body = [
                'code' => $this->code,
                'message' => $message,
                'data' => $this->data
            ];

            if (empty($body['message'])) {
                $body['code'] = ErrorCode::FAIL;
                $body['message'] = ErrorCode::getMessage(ErrorCode::FAIL);
            }

        } else {
            $body = [
                'code' => ErrorCode::SUCCESS,
                'message' => ErrorCode::getMessage(ErrorCode::SUCCESS),
                'data' => $this->data
            ];
        }
        $this->logRequestAndResponse($body, $errorDetail);
        return $this->response->json($body);
    }

    /**
     * Notes:失败返回
     * 2024/5/28
     * @param int|string $code 错误码
     * @param int $errorLine 异常相关行号
     * @param string $errorFile 产生异常的文件名
     * @param string $message 异常信息
     * @return ResponseInterface
     * @throws \Exception
     */
    public function responseError(int|string $code,int $errorLine,string $errorFile ,string $message = ""): ResponseInterface
    {
        $this->code = $code?:ErrorCode::FAIL;
        $message = ErrorCode::getMessage($this->code)?:ErrorCode::getMessage(ErrorCode::FAIL);
        $this->data = (Object)[];
        return $this->responseJson($errorLine,$errorFile,$message);
    }

    /**
     * Notes:成功返回
     * 2024/5/28
     * @param array|object $data 数据体
     * @param int $code
     * @return ResponseInterface
     * @throws \Exception
     */
    public function responseSuccess(array|object $data,int $code=0): ResponseInterface
    {
        $this->code = $code?:ErrorCode::SUCCESS;
        $this->data = $data;
        return $this->responseJson();
    }

    /**
     * Notes:日志记录
     * 2025/5/28
     * @param array|object $body
     * @param array $errorDetail
     * @return void
     * @throws \Exception
     */
    private function logRequestAndResponse(array|object $body, array $errorDetail): void
    {
        $requestId = $this->request->getHeaders()['x-request-id'][0] ?? "null";
        $logMessage = sprintf("%s %s %s %s %s %s %s",
            $this->ip,
            "RequestId:" . $requestId,//nginx侧请求ID
            "Method:" . $this->request->getMethod(),
            "Url:" . $this->request->getUri(),
            "RequestBody:" . Json::encode($this->request->post()),
            "Response:" . Json::encode($body),
            "ErrorDetail:" . Json::encode($errorDetail, JSON_UNESCAPED_UNICODE)
        );
        if (env("FULL_LOGS")){//开启全量日志
            if ($this->code!=ErrorCode::SUCCESS){//错误日志
                \App\Service\LogService::writeLog("", $logMessage, "error");//日志拆分
                $this->logger->error($logMessage);//hyperf 日志(框架不会进行拆分)
            }else{//正常日志
                \App\Service\LogService::writeLog("", $logMessage);//日志拆分
                $this->logger->info($logMessage);//hyperf 日志(框架不会进行拆分)
            }
        }else{//没有开启全量日志,只记录错误日志
            if ($this->code!=ErrorCode::SUCCESS){//错误日志
                \App\Service\LogService::writeLog("", $logMessage, "error");//日志拆分
                $this->logger->error($logMessage);//hyperf 日志(框架不会进行拆分)
            }
        }
    }
}
